<?php defined('SYSPATH') OR die('No direct access allowed.');

class Sintatico extends Core_Sintatico {

	private $error = array();
	
	public function __construct(){
		
	}
	
	/**
	 * Função para analise de entradas contra nossa gramatica
	 * @param $entrada - vetor de tokens
	 * @return array 
	 */
	public function analizaEntrada($entrada){
		if(is_array($entrada)){
			$entrada[] = '$';
			$this->entrada = $entrada;
			$this->pilha = array('$','<COMANDO>');
			$this->saida = array();
			$this->arvore = $this->pilha;
		}else{
			throw new Exception('entrada deve ser um array.');
		}
		try {
			$this->analizeSintatica();
		}catch(AnalysisError $le){
			$this->error[] = $le->getMessage();
			//echo $le->getMessage();
		}
		//$as = new ArvoreSintatica($this);
		//var_dump($this->getSaida());
		//echo $as->getArvoreYahoo();
		//die();
	}

	private function analizeSintatica(){
		$topoPilha = $this->getTopoPilha();
		$token = $this->nextToken();
		$elemento = $token->getId();
		//var_dump($this->pilha);
		while($topoPilha!='$'){
			//echo $topoPilha.', '.$elemento."<br>\n";
			/*
			if(!in_array($elemento, $this->tokens)){
				throw new AnalysisError('ERRO SINTATICO0: Token '.$token->getId().'['.$token->getLexeme().']'.' inesperado na linha: '.$token->getRow().' coluna: '.$token->getCol(), $this->posicao);
			}
			*/
			if(in_array($topoPilha, $this->tokens)){
				//se $topPilha é um terminal
				if($topoPilha==$elemento){
					$this->retiraPilha();
					$topoPilha = $this->getTopoPilha();
					$token = $this->nextToken();
					$elemento = $token->getId();
					//echo "proximo token \n";
				}else{
					//erro elemento não esperado
					//die('erro1:'.$topoPilha.', '.$elemento);
					throw new AnalysisError('ERRO SINTATICO1: Token '.$token->getId().'['.$token->getLexeme().']'.' inesperado na linha: '.$token->getRow().' coluna: '.$token->getCol(), $this->posicao);
				}
			}else if($this->tabela[$topoPilha][$elemento]!=''){
				$numero_producao= $this->tabela[$topoPilha][$elemento];
				$this->saida[] = $numero_producao;
				$producoes = $this->regras[$numero_producao];
				//$this->arvore[]
				$this->retiraPilha();
				$this->colocaPilha($producoes);
				$topoPilha = $this->getTopoPilha();
				//$elemento = $this->nextToken();
				//var_dump($elemento);
				//die();	
			}else{
				//erro
				//die('erro2:'.$topoPilha.', '.$elemento);
				throw new AnalysisError('ERRO SINTATICO2: Token '.$token->getId().'['.$token->getLexeme().']'.' inesperado na linha: '.$token->getRow().' coluna: '.$token->getCol(), $this->posicao);
			}
		}
		if($elemento!='$'){
			//erro
			//die('erro3:'.$topoPilha.', '.$elemento);
			throw new AnalysisError('ERRO SINTATICO3: $ Era esperado', $this->posicao);
		}
	}
	
	
	public function getEntrada(){
		return $this->entrada;
	}
	public function getSaida(){
		return $this->saida;
	}
	public function getRegras(){
		return $this->regras;
	}
	public function getTerminais(){
		return $this->token;
	}
	public function getNaoTerminais(){
		return $this->naoterminais;
	}
	
	public function geraArvore($elemArray){
		$result = '';
		foreach ($elemArray as $elem) {
			if(in_array($elem)){
				$result = '<ul>'.$elem.'<li>'.$this->geraArvore($elem).'</li></ul>';
			}else{
				$result = '<li>'.$elem.'</li>';
			}
		}
		return $result;
	}
	/**
	 * Cria uma lista de itens a serrem mostrados na tela baseado nas regras percorridas pela saida
	 * @param $regra int - regra a escrever.
	 * @return string
	 */
	public function criaArvore2($regra){
		$result = '';
		$regrasProducoes 	= $this->regras[$regra];
		$regrasNome			= $this->regrasByName[$regra];
		foreach ($regrasProducoes as $r) {
			if(in_array($r, $this->regrasByName)){//se for 
				$result = '<ul>'.$regrasNome.'<li>'.$this->geraArvore($elem).'</li></ul>';
			}else{
				$result = '<li>'.$elem.'</li>';
			}
		}
		return $result;
	}
	public function criaArvore(){
		$arvore = array();
		foreach ($this->saida as $r) {
			$regraTitulo= $this->regrasByName[$r];
			$regraDef	= $this->regras[$r];
			if(in_array($elem)){//se for 
				$result = '<ul>'.$elem.'<li>'.$this->geraArvore($elem).'</li></ul>';
			}else{
				$result = '<li>'.$elem.'</li>';
			}
		}
		return $arvore;
	}
	public function criaArvoreArray(){
		
	}
	public function getError(){
		return $this->error;
	}
    
} // End Sintatico